import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import axios from 'axios';
import { setLoading } from './uiSlice';

// Types
interface Pattern {
  _id: string;
  name: string;
  category: 'Creational' | 'Structural' | 'Behavioral';
  description: string;
  intent: string;
  applicability: string;
  structure: string;
  participants: string;
  collaborations: string;
  consequences: string;
  implementation: string;
  sampleCode: string;
  knownUses: string;
  relatedPatterns: string[];
  order: number;
}

interface PatternState {
  patterns: Pattern[];
  currentPattern: Pattern | null;
  loading: boolean;
  error: string | null;
}

const initialState: PatternState = {
  patterns: [],
  currentPattern: null,
  loading: false,
  error: null
};

// Get all patterns
export const getPatterns = createAsyncThunk(
  'patterns/getPatterns',
  async (_, { dispatch, rejectWithValue }) => {
    try {
      dispatch(setLoading({ key: 'patterns', value: true }));
      
      const token = localStorage.getItem('token');
      
      if (!token) {
        return rejectWithValue('No token');
      }
      
      const config = {
        headers: {
          'x-auth-token': token
        }
      };
      
      const res = await axios.get('/api/patterns', config);
      
      dispatch(setLoading({ key: 'patterns', value: false }));
      return res.data;
    } catch (err: any) {
      dispatch(setLoading({ key: 'patterns', value: false }));
      return rejectWithValue(err.response?.data?.msg || 'Server Error');
    }
  }
);

// Get pattern by ID
export const getPatternById = createAsyncThunk(
  'patterns/getPatternById',
  async (patternId: string, { dispatch, rejectWithValue }) => {
    try {
      dispatch(setLoading({ key: 'patterns', value: true }));
      
      const token = localStorage.getItem('token');
      
      if (!token) {
        return rejectWithValue('No token');
      }
      
      const config = {
        headers: {
          'x-auth-token': token
        }
      };
      
      const res = await axios.get(`/api/patterns/${patternId}`, config);
      
      dispatch(setLoading({ key: 'patterns', value: false }));
      return res.data;
    } catch (err: any) {
      dispatch(setLoading({ key: 'patterns', value: false }));
      return rejectWithValue(err.response?.data?.msg || 'Server Error');
    }
  }
);

// Get patterns by category
export const getPatternsByCategory = createAsyncThunk(
  'patterns/getPatternsByCategory',
  async (category: 'Creational' | 'Structural' | 'Behavioral', { dispatch, rejectWithValue }) => {
    try {
      dispatch(setLoading({ key: 'patterns', value: true }));
      
      const token = localStorage.getItem('token');
      
      if (!token) {
        return rejectWithValue('No token');
      }
      
      const config = {
        headers: {
          'x-auth-token': token
        }
      };
      
      const res = await axios.get(`/api/patterns/category/${category}`, config);
      
      dispatch(setLoading({ key: 'patterns', value: false }));
      return res.data;
    } catch (err: any) {
      dispatch(setLoading({ key: 'patterns', value: false }));
      return rejectWithValue(err.response?.data?.msg || 'Server Error');
    }
  }
);

const patternSlice = createSlice({
  name: 'patterns',
  initialState,
  reducers: {
    clearCurrentPattern: (state) => {
      state.currentPattern = null;
    },
    clearPatternError: (state) => {
      state.error = null;
    }
  },
  extraReducers: (builder) => {
    builder
      // Get all patterns
      .addCase(getPatterns.pending, (state) => {
        state.loading = true;
      })
      .addCase(getPatterns.fulfilled, (state, action: PayloadAction<Pattern[]>) => {
        state.loading = false;
        state.patterns = action.payload;
      })
      .addCase(getPatterns.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string;
      })
      // Get pattern by ID
      .addCase(getPatternById.pending, (state) => {
        state.loading = true;
      })
      .addCase(getPatternById.fulfilled, (state, action: PayloadAction<Pattern>) => {
        state.loading = false;
        state.currentPattern = action.payload;
      })
      .addCase(getPatternById.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string;
      })
      // Get patterns by category
      .addCase(getPatternsByCategory.pending, (state) => {
        state.loading = true;
      })
      .addCase(getPatternsByCategory.fulfilled, (state, action: PayloadAction<Pattern[]>) => {
        state.loading = false;
        state.patterns = action.payload;
      })
      .addCase(getPatternsByCategory.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string;
      });
  }
});

export const { clearCurrentPattern, clearPatternError } = patternSlice.actions;

export default patternSlice.reducer; 